package com.lwc.cfdns.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.ThreadPoolExecutor;

/**
 * 线程池配置
 *
 * @author luwc
 * @title ThreadPoolConfig
 * @description
 * @time 2023/7/24 16:19:09
 * @version: 1.0
 */
@Configuration
@EnableAsync// 开启异步调用
public class ThreadPoolConfig {
    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();//获取CPU个数
    private static final int COUR_SIZE = CPU_COUNT * 2;//核心线程数量--cpu个数的两倍
    private static final int MAX_COUR_SIZE = CPU_COUNT * 4;//最大线程数一般设置为cpu个数的四倍
    private static final int queueCapacity = MAX_COUR_SIZE * 4;// 队列最大长度
    private static final int keepAliveSeconds = 300;// 线程池维护线程所允许的空闲时间

    // 接下来配置一个bean，配置线程池。
    @Bean("threadPoolTaskExecutor")
    public ThreadPoolTaskExecutor threadPoolTaskExecutor() {
        ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
        threadPoolTaskExecutor.setCorePoolSize(COUR_SIZE);//设置核心线程数
        threadPoolTaskExecutor.setMaxPoolSize(MAX_COUR_SIZE);//配置最大线程数
        threadPoolTaskExecutor.setQueueCapacity(queueCapacity);//配置队列容量（这里设置成最大线程数的四倍）
        threadPoolTaskExecutor.setKeepAliveSeconds(keepAliveSeconds);
        threadPoolTaskExecutor.setThreadNamePrefix("threadPoolTaskExecutor");//给线程池设置名称

        /** 拒绝策略，有以下四种 **/
//        （1）ThreadPoolExecutor.AbortPolicy 丢弃任务，并抛出 RejectedExecutionException 异常。
//        （2）ThreadPoolExecutor.CallerRunsPolicy：该任务被线程池拒绝，由调用 execute方法的线程执行该任务(同步)。
//        （3）ThreadPoolExecutor.DiscardOldestPolicy ： 抛弃队列最前面的任务，然后重新尝试执行任务。
//        （4）ThreadPoolExecutor.DiscardPolicy，丢弃任务，不过也不抛出异常。
//        也可以自己实现RejectedExecutionHandler接口来自定义拒绝策略
        threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());// 设置任务的拒绝策略
        //初始化线程池
        threadPoolTaskExecutor.initialize();
        return threadPoolTaskExecutor;
    }
}
